﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;

using PGMHelper;

namespace OpenSees.XML
{
    /// <summary>
    /// 序列化容器
    /// </summary>
    [XmlRoot("OpenSees")]
    public class BasicXML
    {
        #region Variables

        /// <summary>
        /// 时间输出
        /// </summary>
        [XmlElement("TimeOutput")]
        public Response TimeOutput { set; get; }

        [XmlIgnore]
        /// <summary>
        /// 响应字典：不包含时间
        /// </summary>
        private Dictionary<int, Response> responseDict { set; get; }

        /// <summary>
        /// 数据
        /// </summary>
        public string Data { set; get; }

        [XmlIgnore]
        /// <summary>
        /// XML文件路径
        /// </summary>
        public string FilePath { set; get; }

        [XmlIgnore]
        /// <summary>
        /// 是否成功序列化
        /// </summary>
        public bool isSuccess { set; get; }

        #endregion

        #region Properties

        [XmlIgnore]
        /// <summary>
        /// 是否存在时间或荷载倍数
        /// </summary>
        /// <returns></returns>
        public bool isTimeEmpty
        {
            get
            {
                return this.TimeOutput == null || this.TimeOutput.ResponseResult == null;
            }
        }

        [XmlIgnore]
        /// <summary>
        /// 获得时间时程
        /// </summary>
        /// <returns></returns>
        public List<float> TimeList
        {
            get
            {
                return this.isTimeEmpty ? new List<float>() :
                    this.TimeOutput.ResponseResult.First();
            }
        }

        [XmlIgnore]
        /// <summary>
        /// 响应字典
        /// </summary>
        private Dictionary<int, Response> ResponseDict
        {
            get
            {
                //实例化
                if (this.responseDict == null)
                    this.responseDict = new Dictionary<int, Response>();
                //键值是否相同
                if (this.responseDict.Count != 0) return this.responseDict;
                //获得响应列表
                var responseList = this.GetResponseList(false);
                //是否为空
                if (responseList.Count == 0) return new Dictionary<int, Response>();
                //获得字典
                this.responseDict = (Dictionary<int, Response>)responseList.CreateDict<int, Response>("ID");
                //返回字典
                return this.responseDict;
            }
        }

        [XmlIgnore]
        /// <summary>
        /// 响应列表
        /// </summary>
        public List<Response> ResponseList
        {
            get
            {
                return this.ResponseDict.Values.ToList();
            }
        }

        [XmlIgnore]
        /// <summary>
        /// 获得响应
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        public Response this[int tag]
        {
            get
            {
                return this.ResponseDict.GetValue(tag);
            }
        }

        [XmlIgnore]
        /// <summary>
        /// 获得响应序列
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="responseType"></param>
        /// <returns></returns>
        public List<float> this[int tag, string responseType]
        {
            get
            {
                return this.ContainsKey(tag) ? this[tag][responseType] :
                new List<float>();
            }
        }

        [XmlIgnore]
        /// <summary>
        /// 获得单元列表
        /// </summary>
        /// <returns></returns>
        public List<int> TagList
        {
            get
            {
                return this.ResponseDict.Count == 0 ? new List<int>() :
                    this.ResponseDict.Keys.ToList();
            }
        }

        [XmlIgnore]
        /// <summary>
        /// 将数据按行进行拆分
        /// </summary>
        private List<string> GetListFromData
        {
            get
            {
                //是否为空
                if (this.Data == string.Empty) return new List<string>();
                //根据换行拆分字符串
                var rowList = this.Data.Split(new string[] { "\n" }, StringSplitOptions.None).ToList();
                rowList = rowList.Where(s => !string.IsNullOrEmpty(s)).ToList();
                rowList.RemoveAt(rowList.Count - 1);
                //清空data数据
                this.Data = string.Empty;
                //返回
                return rowList;
            }
        }

        #endregion

        #region Constructs

        /// <summary>
        /// 空的构造函数
        /// </summary>
        public BasicXML()
        {
            this.TimeOutput = new Response(new List<string> { "time" });
            this.Data = string.Empty;
            this.FilePath = string.Empty;
            this.isSuccess = false;
        }

        #endregion

        #region Virutal

        [XmlIgnore]
        /// <summary>
        /// 结果是否完整
        /// </summary>
        /// <returns></returns>
        public virtual bool isObjectDeserialize
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// 获得响应基类列表
        /// </summary>
        /// <returns></returns>
        public virtual List<Response> GetResponseList(bool includeTime)
        {
            return this.GetBasicResponseList(includeTime);
        }
      
        /// <summary>
        /// 时间序列列表
        /// </summary>
        protected List<Response> GetBasicResponseList(bool includeTime)
        {
            return (includeTime && !this.isTimeEmpty) ?
                new List<Response> { this.TimeOutput } :
                new List<Response>();
        }

        #endregion

        /// <summary>
        /// 判断键值是否存在
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        public bool ContainsKey(int tag)
        {
            return this.ResponseDict.ContainsKey(tag);
        }

        /// <summary>
        /// Recorder记录的响应类型
        /// </summary>
        /// <returns></returns>
        public List<string> GetResponseTypeList(bool includeTime)
        {
            //初始化
            var typeList = new List<string>();
            //遍历响应列表
            this.GetResponseList(includeTime).ForEach(response =>
            {
                response.ResponseTypes.ForEach(typeDesp =>
                {
                    if (!typeList.Contains(typeDesp)) typeList.Add(typeDesp);
                });
            });
            //返回列表
            return typeList;
        }

        /// <summary>
        /// 从DATA中获取计算结果
        /// </summary>
        public bool SetResultFromData()
        {
            return this.SetResultFromData(this.GetResponseList(false));
        }

        /// <summary>
        /// 从DATA中获取计算结果
        /// </summary>
        protected bool SetResultFromData(List<Response> responseList)
        {
            //数据已处理
            if (this.Data == string.Empty) return MessageBoxExtern.Error("DATA is Empty!");
            //response_list为空
            if (responseList == null || responseList.Count == 0)
                return MessageBoxExtern.Error("No Response Type Existed!");
            //初始化分析结果读取容器
            this.initialResultContainer(responseList);
            //获得记录的元素数目
            var recorderNumber = this.GetRecorderItemsNum(responseList);
            //遍历行
            foreach (var row in this.GetListFromData)
            {
                //获得单元格的值
                var cellList = WilsonHelper.SplitStr(row);
                //初始化
                int cellIndex = new int();
                //单元格的值必须大Response的数目（大于1则第一列为荷载倍数）
                if (cellList.Count < recorderNumber)
                    return MessageBoxExtern.Error("The Data is Incomplete!");
                //是否存在荷载倍数
                else if (cellList.Count == recorderNumber + 1)
                    if (!this.TimeOutput.SetResponse(cellList, ref cellIndex)) return false;
                //遍历获得节点分析结果
                for (; cellIndex < cellList.Count; cellIndex++)
                {
                    foreach (var response in responseList)
                        //设定响应结果
                        if (!response.SetResponse(cellList, ref cellIndex))
                            return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 初始化分析结果读取容器
        /// </summary>
        /// <returns></returns>
        private void initialResultContainer(List<Response> responseList)
        {
            //时间序列初始化
            this.TimeOutput = this.TimeOutput == null ?
                new Response(new List<string> { "time" }) :
                this.TimeOutput.initialResponseResult();
            //初始化节点分析结果
            foreach (var response in responseList)
                response.initialResponseResult();
        }

        /// <summary>
        /// 记录的对象数目
        /// </summary>
        /// <param name="responseList"></param>
        /// <returns></returns>
        private int GetRecorderItemsNum(List<Response> responseList)
        {
            //对象数目
            int itemsnum = new int();
            //遍历结果
            responseList.ForEach(response => itemsnum += response.Count);
            //返回对象数目
            return itemsnum;
        }
    }
}
